import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

public class LaplaceUnigramLanguageModel implements LanguageModel {
	protected Set<String> words;
	protected SortedMap<String,Integer> map ;
  /** Initialize your data structures in the constructor. */
  public LaplaceUnigramLanguageModel(HolbrookCorpus corpus) {
    
    words = new HashSet<String>();
    map = new TreeMap<String,Integer>();
    
    train(corpus);
  }

  /** Takes a corpus and trains your language model. 
    * Compute any counts or other corpus statistics in this function.
    */
  
  public void train(HolbrookCorpus corpus) {
	    for(Sentence sentence : corpus.getData()) { // iterate over sentences
	      for(Datum datum : sentence) { // iterate over words
	        String word = datum.getWord(); // get the actual word
	        words.add(word);
	        Integer c = map.get(word);
	        if (c== null) c=0;
	       c++;
	       map.put(word, c);
	      }
	     
	    }
	    
	    //System.out.println("\n"+map.get("was"));
	  }

  
	  /** Takes a list of strings as argument and returns the log-probability of the 
	    * sentence using your language model. Use whatever data you computed in train() here.
	    */
	  public double score(List<String> sentence) {
	    double score = 0.0;
	     // uniform log-probability of log(1/V)
	    for(String word : sentence) { // iterate over words in the sentence
	    	if(map.get(word)!=null){
	    		//System.out.println(map.get(word)+" "+ words.size()+" "+map.size());
	    		
	    		double intCount=(double)(map.get(word)+1)/(words.size()+sentence.size());
	    		//System.out.println(map.get(word)+" "+ words.size()+" "+intCount);
	    		double probability = Math.log(intCount);
	    	score += probability;
	    	}
	    	else
	    	{
	    		//double intCount=(double)(1/(words.size()+map.size()));
	    	//	System.out.println(words.size()+" "+intCount);
	    		double probability = Math.log(0.0003);
		    	score += probability;
	    	}
	    	
	    	//System.out.println( "Word : "+ word+ " Score : "+ score);
	    }
	    // NOTE: a simpler method would be just score = sentence.size() * - Math.log(words.size()).
	    // we show the 'for' loop for insructive purposes.
	    return score;
	  }
}
